#include "TutorApp3.h"

#ifdef WIN32
#ifdef Tutorial3_EXPORTS
#define TUTORAPP3_API __declspec(dllexport)
#else
#define TUTORAPP3_API __declspec(dllimport)
#endif
#else
#define TUTORAPP3_API
#endif

extern "C" TUTORAPP3_API Blobz::BaseApplication* GetInstance()
{
	Tutorial3::TutorApp3* pTutorial = new Tutorial3::TutorApp3();
	return (Blobz::BaseApplication*)pTutorial;
}

extern "C" TUTORAPP3_API unsigned int GetMajorReleaseVersion()
{
	return NUI_RELEASE_MAJOR_VER;
}

extern "C" TUTORAPP3_API unsigned int GetMinorReleaseVersion()
{
	return NUI_RELEASE_MINOR_VER;
}

extern "C" TUTORAPP3_API const char* GetAppName()
{
	return "Tutorial3";
}

namespace Tutorial3
{
	/**
	* Constructor
	*/
	TutorApp3::TutorApp3()
	{
	}

	/**
	* Destructor
	*/
	TutorApp3::~TutorApp3()
	{
	}

	/**
	* Loads graphics, music and gui components
	*/
	bool TutorApp3::onInitialize()
	{
		// Tell the application to use a fixed aspect ratio so that our view content is not stretched
		getWindow().setUseFixedRatio(true);
		
		// Save the application directory for easier access
		QString appDir = getApplicationDirectory();

		// load the background texture
		mBackgroundTexture.load(getApplicationDirectory()+"bg.png", true);

		// Load a *.ttf font at the specified font size and set render scale
		mExampleFont.loadDefaultSystemFont();
		mExampleFont.setRenderScale(0.0002f*getWindow().getWindowAspect());

		// Create the slider
		mpExampleSlider = mExampleGUIManager.addSlider("ExampleSlider", appDir+"sliderbar.png", appDir+"slider_unselected.png", appDir+"slider_selected.png");
		mpExampleSlider->setPosition(QVector2D(0.15f*getWindow().getWindowAspect(), 0.5f));
		mpExampleSlider->setRotation(Blobz::degToRad(90));
		mpExampleSlider->setSize(QVector2D(0.40f, 0.03f));
		mpExampleSlider->setMinMax(0.01f, 0.08f);
		mpExampleSlider->setValue(0.03f);

		// Load the particle effects
		mParticleEmitter.setPath(getApplicationDirectory().toStdString());
		mParticleEmitter.load(getApplicationDirectory().toStdString()+"ParticleSettings.cfg");
		QVector2D emitterPos = QVector2D(mpExampleSlider->getPosition().x()+0.25f, mpExampleSlider->getPosition().y()-0.175f);
		mParticleEmitter.setPosition(emitterPos);
		

		// Create a button with text 
		// The button will expand to fit the text
		Blobz::Button *exampleButton = mExampleGUIManager.addButton("BlipButton", appDir+"greenUnpress.png", appDir+"greenPress.png", "Blip Button");
		exampleButton->setPosition(QVector2D(getWindow().getWindowAspect()*0.7f, 0.6f));
		exampleButton->setSize(QVector2D(0.1f,0.1f));

		// Load the sound file
		mExampleSound.load(appDir+"audio/blipp1.wav", Blobz::AudioType_Sound);

		// Load the background music
		mExampleMusic.load(appDir+"audio/music.mp3", Blobz::AudioType_Music);

		//Load background music controls
		Blobz::Button *playButton = mExampleGUIManager.addButton("PlayButton", appDir+"small_play.png", appDir+"small_play_pressed.png");
		playButton->setPosition(exampleButton->getPosition()+QVector2D(-0.1f, -0.25f));
		playButton->setSize(QVector2D(0.17f, 0.1f));

		Blobz::Button *pauseButton = mExampleGUIManager.addButton("PauseButton", appDir+"small_pause.png", appDir+"small_pause_pressed.png");
		pauseButton->setPosition(playButton->getPosition()+QVector2D(0.2f, 0.0f));
		pauseButton->setSize(QVector2D(0.17f, 0.1f));

		mExampleGUIManager.addListener(this);

		return true;
	}

	/**
	* onReload Handler
	*/
	void TutorApp3::onReload()
	{
	}

	/**
	* Unloads graphics, music and GUI components
	*/
	void TutorApp3::onDeinitialize()
	{
		// Remember to unload every object
		mBackgroundTexture.unload();
		mExampleFont.unload();

		mExampleGUIManager.unload();
		mParticleEmitter.unload();

		mExampleSound.unload();
		mExampleMusic.unload();
	}

	/**
	* Triggered on every frame update
	* \param inFrameTime Time since last update ( in seconds )
	*/
	void TutorApp3::onUpdate(float inFrameTime)
	{
		mExampleGUIManager.update(inFrameTime);
		mParticleEmitter.update(inFrameTime);
	}

	/**
	* Render the graphics and other opengl job here
	*/
	void TutorApp3::onDraw()
	{
		// Tell Snowflake that we want to start rendering
		getWindow().enableRendering();

		// Screen setup, part of the Snowflake framework
		getWindow().defaultRenderSetup();

		// Render the background texture
		renderBackground();

		// Render all GUI elements
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		mExampleGUIManager.render();

		// Need to disable depth test here since Blobz::GUIManager enables it after render
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		mParticleEmitter.render();

		// Render Particle slider message
		const QString sliderMessage = "Drag slider to change particle parameters.";
		QVector2D sliderMessagePos = mpExampleSlider->getPosition()+QVector2D(0.125f, -0.25f);
		float w = mExampleFont.stringWidth(sliderMessage);
		float h = mExampleFont.stringHeight(sliderMessage);
		glColor4f(0, 0, 0, 1);
		mExampleFont.print(sliderMessage, sliderMessagePos.x(), sliderMessagePos.y());

		// Render background music control message
		const QString bgMessage = "Use the controls above to play and pause background music";
		QVector2D bgMessagePos = mExampleGUIManager.getComponent("PlayButton")->getPosition()+QVector2D(0.1f, -0.1f);
		w = mExampleFont.stringWidth(bgMessage);
		h = mExampleFont.stringHeight(bgMessage);
		glColor4f(0, 0, 0, 1);
		mExampleFont.print(bgMessage, bgMessagePos.x(), bgMessagePos.y());

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);

		// Tell Snowflake that we're done rendering
		getWindow().disableRendering();
	}

	/**
	* Triggered when there is a finger down event on the screen
	* \param inData holds the touch information
	*/
	void TutorApp3::onFingerDown(const TouchListener::TouchData& inData)
	{
		mExampleGUIManager.onFingerDown(inData);
	}

	/**
	* Triggered when there is a finger up event on the screen
	* \param inData holds the touch information
	*/
	void TutorApp3::onFingerUp(const TouchListener::TouchData& inData)
	{
		mExampleGUIManager.onFingerUp(inData);
	}

	/**
	* Triggered when there is a finger update event on the screen
	* \param inData holds the touch information
	*/
	void TutorApp3::onFingerUpdate(const TouchListener::TouchData& inData)
	{
		mExampleGUIManager.onFingerUpdate(inData);
	}

	/**
	* Triggered when there is a finger moves out of the screen or application window
	* \param inData holds the touch information
	*/
	void TutorApp3::onFingerExit(const TouchListener::TouchData& inData)
	{
		onFingerUp(inData);
	}

	// OnGUIEvent
	void TutorApp3::onGUIEvent(Blobz::GUIBase* inpComponent, Blobz::GUIEvent inGUIEvent, Blobz::FingerEvent inFingerEvent)
	{
		// Check if the event was a Button Released event
		if(inGUIEvent==Blobz::Button_Released)
		{
			// Compare with the button names that we know to delegate appropriate tasks
			if(inpComponent->getName() == "BlipButton")
				mExampleSound.play();
			else if(inpComponent->getName() == "PlayButton")
				mExampleMusic.play(true);
			else if(inpComponent->getName() == "PauseButton")
				mExampleMusic.pause();
		}
		// Otherwise check if it was a slider value change
		else if(inGUIEvent==Blobz::Slider_ValueChange)
		{
			// No comparison necessary since there is only one slider

			// Change Particle parameters based on slider values
			QVector2D pos = QVector2D(mpExampleSlider->getPosition().x()+0.25f, mpExampleSlider->getPosition().y()-0.175f);
			mParticleEmitter.setPosition(pos);
			mParticleEmitter.setParticleSize(mpExampleSlider->getValue());
			mParticleEmitter.setMaxVelocity(10*mpExampleSlider->getValue());
		}
	}

	/**
	* Render Background
	*/
	void TutorApp3::renderBackground()
	{
		// Render the background texture
		const QVector2D windowSize(getWindow().getWindowAspect(), 1.0f);
		const QVector2D mPosition(0.0f, 0.0f);

		glEnable(GL_TEXTURE_2D);

		// Binds the texture ID to OpenGL so it can be used
		glBindTexture(GL_TEXTURE_2D, mBackgroundTexture.getID()); 
		// Begin drawing GLQuads
		glBegin(GL_QUADS);
			glColor4f(1, 1, 1, 1);
			glTexCoord2f(0,1);
			glVertex2f(mPosition.x(), mPosition.y());
			glTexCoord2f(1,1);
			glVertex2f(mPosition.x()+windowSize.x(), mPosition.y());
			glTexCoord2f(1,0);
			glVertex2f(mPosition.x()+windowSize.x(), mPosition.y()+windowSize.y());
			glTexCoord2f(0,0);
			glVertex2f(mPosition.x(), mPosition.y()+windowSize.y());
			glEnd();
		glDisable(GL_TEXTURE_2D);
	}
}
